package com.sds.thesis.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.Rows;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.sds.thesis.model.*;
import com.sds.thesis.policy.ServerTablePolicy;
import com.sds.thesis.service.PaperService;
import com.sds.thesis.service.TemplateJsonService;
import com.sds.thesis.util.TypeUtil;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

@Service
public class PaperServiceImpl implements PaperService {

    private static final Logger log = LoggerFactory.getLogger(PaperServiceImpl.class);

    @Autowired
    private TemplateJsonService templateJsonService;

    @Override
    public void generatePaper() throws IOException {
        //解决poi-tl渲染docx文件时，报错：Zip bomb detected! The file would exceed the max.
        ZipSecureFile.setMinInflateRatio(-1.0d);

        //poi-tl 配置
        ConfigureBuilder builder = Configure.builder();
        builder.useSpringEL(true);

        // 解析基本信息
//        Paper paper = templateJsonService.handleTemplateJson("src/main/resources/thesis/.template.json");
        Paper paper = templateJsonService.handleTemplateJson("C:\\Users\\32964\\Desktop\\.template.json");

        // 处理系统模块
        doSystemModule(paper);

        // 处理展示页面
        doPageShow(paper);

        // 处理表结构
        doTableStructure(paper);
        builder.bind("InfoTablePolicy", new LoopRowTableRenderPolicy());

        // 处理er图
        doErGraph(paper);

        // 处理测试表格
        doTestCase(paper);
        builder.bind("queryEq",new ServerTablePolicy());
        builder.bind("queryCase",new ServerTablePolicy());
        builder.bind("editEq",new ServerTablePolicy());
        builder.bind("editCase",new ServerTablePolicy());

        // 处理测试页面
        doTestProc(paper);

        //渲染文件
        XWPFTemplate compile = XWPFTemplate.compile("src/main/resources/thesis/template.docx", builder.build());
        compile.render(paper);

        //输出为文件，指定输出文件名
        compile.writeToFile("target/"+paper.getProjectName()+"的设计与实现.docx");
    }

    /**
     * 处理测试页面
     *
     * @param paper
     */
    private void doTestProc(Paper paper) {
        List<TestProc> testProcList = new ArrayList<>();
        for (Map.Entry<String, String> entry : paper.getMetaNameMap().entrySet()) {
            String tableZhName = entry.getKey();

            TestProc testProc = new TestProc();
            testProc.setTableZhName(tableZhName);

            testProcList.add(testProc);
        }

        paper.setTestProcList(testProcList);
    }

    /**
     * 处理展示页面
     *
     * @param paper
     */
    private void doPageShow(Paper paper) {
        List<PageShow> pageShowList = new ArrayList<>();
        for (Map.Entry<String, String> entry : paper.getMetaNameMap().entrySet()) {
            String tableZhName = entry.getKey();

            PageShow pageShow = new PageShow();
            pageShow.setTableZhName(tableZhName);

            pageShowList.add(pageShow);
        }

        paper.setPageShowList(pageShowList);
    }

    /**
     * 处理系统模块
     *
     * @param paper
     */
    private void doSystemModule(Paper paper) throws IOException {
        List<SysModule> sysModuleList = new ArrayList<>();

        Path sysModulePath = Paths.get("src/main/resources/thesis/xml/system_module.xml");
        String sysModuleXml = new String(Files.readAllBytes(sysModulePath));
        for (Map.Entry<String, String> entry : paper.getMetaNameMap().entrySet()) {
            String tableZhName = entry.getKey();

            SysModule sysModule = new SysModule();
            sysModule.setTableZhName(tableZhName);
            sysModule.setSysModuleXML(sysModuleXml.replace("entity", tableZhName));

            sysModuleList.add(sysModule);
        }

        paper.setSysModuleList(sysModuleList);
    }

    /**
     * 处理测试表格
     *
     * @param paper
     */
    private void doTestCase(Paper paper) {
        List<TestCase> testCaseList = new ArrayList<>();
        for (Map.Entry<String, String> entry : paper.getMetaNameMap().entrySet()) {
            String tableZhName = entry.getKey();
            String tableName = entry.getValue();
            JSONObject targetTable = paper.getTableList().stream()
                    .map(JSONObject.class::cast)
                    .filter(table -> tableName.equals(table.getString("tableName")))
                    .findFirst()
                    .orElse(null);
            JSONArray columns = targetTable.getJSONArray("columns");

            List<RowRenderData> qeRenderDataList = new ArrayList<>();
            List<RowRenderData> qcRenderDataList = new ArrayList<>();
            List<RowRenderData> eeRenderDataList = new ArrayList<>();
            List<RowRenderData> ecRenderDataList = new ArrayList<>();
            List<Map<String, Object>> qeGroupDataList = new ArrayList<>();
            List<Map<String, Object>> qcGroupDataList = new ArrayList<>();
            List<Map<String, Object>> eeGroupDataList = new ArrayList<>();
            List<Map<String, Object>> ecGroupDataList = new ArrayList<>();

            for (int i = 0; i < columns.size(); i++) {
                JSONObject column = columns.getJSONObject(i);

                String comment = column.getString("comment");
                String type = TypeUtil.getType(column.getString("type"));
                if (comment.toLowerCase().contains("id")) {
                    continue;
                }
                if ("String".equals(type)) {
                    qeRenderDataList.add(Rows.of(comment, "存在库中的"+comment, "匹配不到"+comment+"\n非法空格").center().create());
                    qcRenderDataList.add(Rows.of(comment, "已有"+comment,"","搜索成功","库存数据").center().create());
                    qcRenderDataList.add(Rows.of(comment, "非已有"+comment,"","搜索失败","库存不存在").center().create());
                    qcRenderDataList.add(Rows.of(comment, "非法字符","空格","搜索失败","非法值").center().create());
                    qcGroupDataList.add(new HashMap<String, Object>() {{
                        put("typeName", comment);
                        put("listSize", 3);
                    }});
                    eeRenderDataList.add(Rows.of(comment, "非空", "空").center().create());
                    ecRenderDataList.add(Rows.of(comment, "不为空", "","添加成功","有效值").center().create());
                    ecRenderDataList.add(Rows.of(comment, "不填", "","添加失败","无效值").center().create());
                    ecGroupDataList.add(new HashMap<String, Object>() {{
                        put("typeName", comment);
                        put("listSize", 2);
                    }});
                }
                if ("Integer".equals(type)) {
                    qeRenderDataList.add(Rows.of(comment, "输入范围内的"+comment, "输入超过"+comment+"数\n非数字").center().create());
                    qcRenderDataList.add(Rows.of(comment, "范围内的"+comment,"","搜索成功","有效值").center().create());
                    qcRenderDataList.add(Rows.of(comment, "不在范围内的"+comment,"","搜索失败","无效值").center().create());
                    qcRenderDataList.add(Rows.of(comment, "非数字","aaa","搜索失败","不合法数据").center().create());
                    qcGroupDataList.add(new HashMap<String, Object>() {{
                        put("typeName", comment);
                        put("listSize", 3);
                    }});
                    eeRenderDataList.add(Rows.of(comment, "非空", "空").center().create());
                    ecRenderDataList.add(Rows.of(comment, "不为空", "","添加成功","有效值").center().create());
                    ecRenderDataList.add(Rows.of(comment, "不填", "","添加失败","无效值").center().create());
                    ecGroupDataList.add(new HashMap<String, Object>() {{
                        put("typeName", comment);
                        put("listSize", 2);
                    }});
                }

            }
//            log.debug("qeRenderDataList=" + qeRenderDataList);
//            log.debug("qcRenderDataList=" + qcRenderDataList);
            TestCase testCase = new TestCase();
            testCase.setTableZhName(tableZhName);
            testCase.setQueryEq(new ServerTableData(qeRenderDataList, qeGroupDataList, 0));
            testCase.setQueryCase(new ServerTableData(qcRenderDataList, qcGroupDataList, 0));
            testCase.setEditEq(new ServerTableData(eeRenderDataList, eeGroupDataList, 0));
            testCase.setEditCase(new ServerTableData(ecRenderDataList, ecGroupDataList, 0));

            testCaseList.add(testCase);
        }

        paper.setTestCaseList(testCaseList);
    }

    /**
     * 处理er图
     *
     * @param paper
     */
    private void doErGraph(Paper paper) throws IOException {
        List<ErGraph> erGraphList = new ArrayList<>();
        for (Map.Entry<String, String> entry : paper.getMetaNameMap().entrySet()) {
            String tableZhName = entry.getKey();
            String tableName = entry.getValue();
            JSONObject targetTable = paper.getTableList().stream()
                    .map(JSONObject.class::cast)
                    .filter(table -> tableName.equals(table.getString("tableName")))
                    .findFirst()
                    .orElse(null);

            JSONArray columns = targetTable.getJSONArray("columns");

            // 字段列表
            List<String> fieldList = new ArrayList<>();
            int count = 1;
            for (int i = 0; i < columns.size(); i++) {
                JSONObject column = columns.getJSONObject(i);
                String comment = column.getString("comment");
                fieldList.add(comment);
                count += 1;
            }
            // 读取relational_graph_count.xml
            Path graphPath = Paths.get("src/main/resources/thesis/xml/relational_graph_" + count + ".xml");
            String erGraphXml = new String(Files.readAllBytes(graphPath));
            erGraphXml = erGraphXml.replace("entity", tableZhName);
            erGraphXml = erGraphXml.replace("filed1", tableZhName + "id");
            for (int i = columns.size()-1; i >= 0; --i) {
                JSONObject column = columns.getJSONObject(i);
                String comment = column.getString("comment");
                log.info("field" + (i+2) + "=" + comment);
                erGraphXml = erGraphXml.replace("filed"+(i+2)+"", comment);
            }

            ErGraph erGraph = new ErGraph();
            erGraph.setTableZhName(tableZhName);
            erGraph.setFieldList(String.join("、", fieldList));
            erGraph.setErGraphXML(erGraphXml);

            erGraphList.add(erGraph);
        }

        paper.setErGraphList(erGraphList);
    }

    /**
     * 处理表结构
     *
     * @param paper
     */
    private static void doTableStructure(Paper paper) {
        List<ListInfoTable> dynamicFlag = new ArrayList<>();

        // 字段表格
        for (Map.Entry<String, String> entry : paper.getMetaNameMap().entrySet()) {
            String metaName = entry.getKey();
            String targetTableName = entry.getValue();
            JSONObject targetTable = paper.getTableList().stream()
                    .map(JSONObject.class::cast)
                    .filter(table -> targetTableName.equals(table.getString("tableName")))
                    .findFirst()
                    .orElse(null);

            log.info("targetTable=" + targetTable);
            JSONArray columns = targetTable.getJSONArray("columns");

            List<String> fieldList = new ArrayList<>();
            List<FieldInfo> fieldInfoList = new ArrayList<>();

            fieldInfoList.add(new FieldInfo(targetTableName + "_id", "String", "是", "否", metaName + "id"));

            for (int i = 0; i < columns.size(); i++) {
                JSONObject column = columns.getJSONObject(i);

                String comment = column.getString("comment");
                String type = TypeUtil.getType(column.getString("type"));
                String isNull = column.containsKey("required") ? "否" : "是";
                String columnName = column.getString("columnName");
                fieldList.add(comment);

                FieldInfo fieldInfo = new FieldInfo();
                fieldInfo.setName(columnName);
                fieldInfo.setType(type);
                fieldInfo.setIsPrimaryKey("否");
                fieldInfo.setIsNull(isNull);
                fieldInfo.setComment(comment);
                fieldInfoList.add(fieldInfo);
            }

            log.info("===========================");
            ListInfoTable listInfoTable = new ListInfoTable();
            listInfoTable.setInfoTablePolicy(fieldInfoList);
            listInfoTable.setTableZhName(metaName);
            listInfoTable.setTableName(targetTableName);
            listInfoTable.setFieldList(String.join("、", fieldList));
            dynamicFlag.add(listInfoTable);
        }

        paper.setListInfoTable(dynamicFlag);
    }
}